﻿using System;
using System.Collections;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Janus.Cores.Linq
{
    public static class LambdaExtension
    {
        #region GetName(获取成员名称)
        /// <summary>
        /// 获取成员名称，范例：t => t.Name,返回 Name
        /// </summary>
        /// <param name="expression">表达式,范例：t => t.Name</param>
        public static string GetName(this Expression expression)
        {
            var memberExpression = GetMemberExpression(expression);
            return GetMemberName(memberExpression);
        }

        /// <summary>
        /// 获取成员表达式
        /// </summary>
        /// <param name="expression">表达式</param>
        public static MemberExpression GetMemberExpression(Expression expression)
        {
            if (expression == null)
                return null;
            switch (expression.NodeType)
            {
                case ExpressionType.Lambda:
                    return GetMemberExpression(((LambdaExpression)expression).Body);
                case ExpressionType.Convert:
                    return GetMemberExpression(((UnaryExpression)expression).Operand);
                case ExpressionType.Equal:
                case ExpressionType.NotEqual:
                case ExpressionType.GreaterThan:
                case ExpressionType.LessThan:
                case ExpressionType.GreaterThanOrEqual:
                case ExpressionType.LessThanOrEqual:
                    return GetMemberExpression(((BinaryExpression)expression).Left);
                case ExpressionType.Call:
                    return GetMemberExpression(((MethodCallExpression)expression).Object);
                case ExpressionType.MemberAccess:
                    return (MemberExpression)expression;
            }
            return null;
        }

        //public static MemberInitExpression GetMemberInitExpression()
        //{
        //    System.Linq.Expressions.NewExpression newAnimal =
        //System.Linq.Expressions.Expression.New(typeof(Animal));

        //    System.Reflection.MemberInfo speciesMember =
        //        typeof(Animal).GetMember("Species")[0];
        //    System.Reflection.MemberInfo ageMember =
        //        typeof(Animal).GetMember("Age")[0];

        //    // Create a MemberBinding object for each member
        //    // that you want to initialize.
        //    System.Linq.Expressions.MemberBinding speciesMemberBinding =
        //        System.Linq.Expressions.Expression.Bind(
        //            speciesMember,
        //            System.Linq.Expressions.Expression.Constant("horse"));
        //    System.Linq.Expressions.MemberBinding ageMemberBinding =
        //        System.Linq.Expressions.Expression.Bind(
        //            ageMember,
        //            System.Linq.Expressions.Expression.Constant(12));

        //    // Create a MemberInitExpression that represents initializing
        //    // two members of the 'Animal' class.
        //    System.Linq.Expressions.MemberInitExpression memberInitExpression =
        //        System.Linq.Expressions.Expression.MemberInit(
        //            newAnimal,
        //            speciesMemberBinding,
        //            ageMemberBinding);
        //}
        /// <summary>
        /// 获取成员名称
        /// </summary>
        private static string GetMemberName(MemberExpression memberExpression)
        {
            if (memberExpression == null)
                return string.Empty;
            string result = memberExpression.ToString();
            return result.Substring(result.IndexOf(".", StringComparison.Ordinal) + 1);
        }

        #endregion

        #region GetValue(获取值)
        /// <summary>
        /// 获取值,范例：t => t.Name == "A",返回 A
        /// </summary>
        /// <param name="expression">表达式,范例：t => t.Name == "A"</param>
        public static object GetValue(this Expression expression)
        {
            if (expression == null)
                return null;
            switch (expression.NodeType)
            {
                case ExpressionType.Lambda:
                    return GetValue(((LambdaExpression)expression).Body);
                case ExpressionType.Convert:
                    return GetValue(((UnaryExpression)expression).Operand);
                case ExpressionType.Equal:
                case ExpressionType.NotEqual:
                case ExpressionType.GreaterThan:
                case ExpressionType.LessThan:
                case ExpressionType.GreaterThanOrEqual:
                case ExpressionType.LessThanOrEqual:
                    return GetValue(((BinaryExpression)expression).Right);
                case ExpressionType.Call:
                    return GetValue(((MethodCallExpression)expression).Arguments.FirstOrDefault());
                case ExpressionType.MemberAccess:
                    return GetMemberValue((MemberExpression)expression);
                case ExpressionType.Constant:
                    return GetConstantExpressionValue(expression);
            }
            return null;
        }

        /// <summary>
        /// 获取属性表达式的值
        /// </summary>
        private static object GetMemberValue(MemberExpression expression)
        {
            if (expression == null)
                return null;
            var field = expression.Member as FieldInfo;
            if (field != null)
            {
                var constValue = GetConstantExpressionValue(expression.Expression);
                return field.GetValue(constValue);
            }
            var property = expression.Member as PropertyInfo;
            if (property == null)
                return null;
            var value = GetMemberValue(expression.Expression as MemberExpression);
            return property.GetValue(value, null);
        }

        /// <summary>
        /// 获取常量表达式的值
        /// </summary>
        private static object GetConstantExpressionValue(Expression expression)
        {
            var constantExpression = (ConstantExpression)expression;
            return constantExpression.Value;
        }

        #endregion

        #region 获取运算符
        /// <summary>
        /// 获取运算符
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static ExpressionType? GetOperator(this Expression expression)
        {
            if (expression == null)
                return null;
            switch (expression.NodeType)
            {
                case ExpressionType.Lambda:
                    return GetOperator(((LambdaExpression)expression).Body);
                case ExpressionType.Convert:
                    return GetOperator(((UnaryExpression)expression).Operand);
            }
            return expression.NodeType;
        }
        #endregion

        #region 扩展
        /// <summary>
        /// Expression 转换为更新语句Set部份
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static string ToUpdater(this LambdaExpression expression)
        {
            string result = string.Empty;
            //获取Update的赋值语句
            var updateMemberExpr = (MemberInitExpression)expression.Body;
            var updateMember = GetMemberExpression(expression);
            //var updateMemberExpr = (MemberInitExpression)updateMember;
            var updateMemberCollection = updateMemberExpr.Bindings.Cast<MemberAssignment>().Select(c => new
            {
                Name = c.Member.Name,
                Value = Expression.Lambda(c.Expression).Compile().DynamicInvoke()// ((ConstantExpression)c.Expression).Value
            });
            result = string.Join(", ", updateMemberCollection.Select(c => string.Format("[{0}]='{1}'", c.Name, c.Value).ToArray()));
            return result;
        }

        /// <summary>
        /// 表达式 转换为Hashtable
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static Hashtable ToHashtable(this LambdaExpression expression)
        {
            var result = new Hashtable();
            //获取Update的赋值语句
            var updateMemberExpr = (MemberInitExpression)expression.Body;
            var updateMemberCollection = updateMemberExpr.Bindings.Cast<MemberAssignment>().Select(c => new
            {
                Key = c.Member.Name,
                Value = Expression.Lambda(c.Expression).Compile().DynamicInvoke()// ((ConstantExpression)c.Expression).Value
            });
            foreach (var item in updateMemberCollection)
            {
                result.Add(item.Key, item.Value);
            }
            //var dic = updateMemberCollection.ToDictionary(c => new { c.Key, c.Value });
            //result = new Hashtable(dic);
            return result;
        }

        /// <summary>
        /// Expression 转换为where条件
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        public static string ToWhere(this LambdaExpression expression)
        {
            string result = string.Empty;
            if (expression != null)
            {
                ConditionBuilder builder = new ConditionBuilder();
                builder.Build(expression);
                result = builder.Condition;
                var args = builder.Arguments.ToList();
                //args.AddRange((updateMemberCollection.Select(c => c.Value)).ToList());
                return string.Format(result, args.ToArray());
            }
            else
            {
                return null;
            }
        }
        #endregion
    }
}
